package com.gitee.kenewstar.migration.function;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.gitee.kenewstar.migration.constants.Const;
import com.gitee.kenewstar.migration.constants.FunctionCode;
import com.gitee.kenewstar.migration.core.AbstractSyncFunction;
import com.gitee.kenewstar.migration.core.ContextParam;
import com.gitee.kenewstar.migration.entity.CommonResult;
import com.gitee.kenewstar.migration.entity.Profile;
import com.gitee.kenewstar.migration.entity.ProfileTl;
import com.gitee.kenewstar.migration.entity.ProfileValue;
import com.gitee.kenewstar.migration.service.ProfileService;
import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 配置维护function
 *
 * @author kenewstar
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ProfileFunction extends AbstractSyncFunction<Profile> {

    private final ProfileService profileService;

    @Override
    protected Class<Profile> parameterType() {
        return Profile.class;
    }

    @Override
    public List<CommonResult> execute(ContextParam contextParam, List<Profile> list) {
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        final List<Profile> profileList = this.profileService.devSelectProfileList(list);
        if (CollUtil.isEmpty(profileList)) {
            return Collections.emptyList();
        }

        final List<Long> profileIds = profileList.stream().map(Profile::getProfileId).collect(Collectors.toList());
        final List<ProfileTl> profileTls = this.profileService.devSelectProfileTl(profileIds);
        final List<ProfileValue> profileValues = this.profileService.devSelectProfileValue(profileIds);

        final Map<Long, List<ProfileTl>> profileTlsMap = profileTls.stream().collect(Collectors.groupingBy(ProfileTl::getProfileId));
        final Map<Long, List<ProfileValue>> profileValuesMap = profileValues.stream().collect(Collectors.groupingBy(ProfileValue::getProfileId));

        contextParam.profileContext = Context.builder().build();
        contextParam.profileContext.profileTlsMap = profileTlsMap;
        contextParam.profileContext.profileValuesMap = profileValuesMap;

        List<CommonResult> resultList = new ArrayList<>(profileList.size());
        for (Profile profile : profileList) {
            CommonResult result = CommonResult.create(true).setTenantId(profile.getTenantId()).setProfileName(profile.getProfileName());
            try {
                contextParam.profileContext.profile = profile;
                this.self().singleExecute(contextParam);
                resultList.add(result);
            } catch (Exception e) {
                resultList.add(result.setSuccessFlag(false).setErrorMsg(e.getMessage()));
                e.printStackTrace();
            }
        }

        return resultList;
    }

    @Override
    public FunctionCode functionCode() {
        return FunctionCode.PROFILE;
    }

    @Override
    @DS(Const.UAT)
    @Transactional(rollbackFor = Exception.class)
    public void singleExecute(ContextParam contextParam) {
        Profile profile = contextParam.profileContext.profile;
        Map<Long, List<ProfileTl>> profileTlsMap = contextParam.profileContext.profileTlsMap;
        Map<Long, List<ProfileValue>> profileValuesMap = contextParam.profileContext.profileValuesMap;


        final Long devId = profile.getProfileId();
        profile.setProfileId(null);
        this.profileService.uatInsertProfile(ListUtil.toList(profile));

        final List<ProfileTl> profileTls = profileTlsMap.get(devId);
        if (CollUtil.isNotEmpty(profileTls)) {
            profileTls.forEach(x -> x.setProfileId(profile.getProfileId()));
            this.profileService.uatInsertProfileTl(profileTls);
        }
        final List<ProfileValue> profileValues = profileValuesMap.get(devId);
        if (CollUtil.isNotEmpty(profileValues)) {
            profileValues.forEach(x -> x.setProfileId(profile.getProfileId()));
            profileValues.forEach(x -> x.setProfileValueId(null));
            this.profileService.uatInsertProfileValue(profileValues);
        }

    }

    @Builder
    @SuppressWarnings("all")
    public static class Context {
        public Profile profile;
        public Map<Long, List<ProfileTl>> profileTlsMap;
        public Map<Long, List<ProfileValue>> profileValuesMap;
    }

}
